package org.jeecg.modules.system.controller;

import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.exceptions.ClientException;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.caocaog.market.constant.MarketConstant;
import com.caocaog.market.entity.ShopBasic;
import com.caocaog.market.merchant.entity.MkMerchantBasic;
import com.caocaog.market.merchant.service.MkMerchantService;
import com.caocaog.market.service.IShopBasicService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.jeecg.common.aspect.annotation.Limit;
import org.jeecg.common.constant.CacheConstant;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.system.api.ISysBaseAPI;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.system.vo.LoginUserSite;
import org.jeecg.common.system.vo.LoginUserSiteArea;
import org.jeecg.common.util.*;
import org.jeecg.common.util.encryption.EncryptedString;
import org.jeecg.modules.base.service.BaseCommonService;
import org.jeecg.modules.system.entity.*;
import org.jeecg.modules.system.model.SysLoginModel;
import org.jeecg.modules.system.service.*;
import org.jeecg.modules.system.util.RandImageUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;

/**
 * @Author scott
 * @since 2018-12-17
 */
@RestController
@RequestMapping("/sys")
@Api(tags = "用户登录")
@Slf4j
public class LoginController {
    // update-begin author:chechen date:20211125 for:让随机生成的验证码不再出现oO01lI这种容易混淆的字符
    private static final String BASE_CHECK_CODES = "qwertyuipkjhgfdsazxcvbnmQWERTYUPLKJHGFDSAZXCVBNM23456789";
    // 第一次登录的常量值
    private static Integer firstLoginValue = 1;
    @Autowired
    private ISysUserService sysUserService;
    @Autowired
    private ISysBaseAPI sysBaseAPI;
    @Autowired
    private ISysLogService logService;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private ISysDepartService sysDepartService;
    @Autowired
    private ISysTenantService sysTenantService;
    @Autowired
    private ISysDictService sysDictService;
    @Resource
    private BaseCommonService baseCommonService;
    @Autowired
    private ISysUserSiteService sysUserSiteService;
    @Autowired
    private MkMerchantService mkMerchantService;
    @Autowired
    private IShopBasicService shopBasicService;
    // private static final String BASE_CHECK_CODES = "oO01lI";
    // update-end author:chechen date:20211125

    @Autowired
    private MkMerchantService merchantService;

    @ApiOperation("分站获取商家登录信息")
    @PostMapping("/toMerchantLogin")
    public Result<JSONObject> toMerchantLogin(@RequestParam String merchantId) {
        MkMerchantBasic merchant = merchantService.findMerchantById(merchantId);
        Assert.notNull(merchant, "Merchant must not be null!");

        // 生成验证码
        String key = RandomUtil.randomString(BASE_CHECK_CODES, 4);
        String code = RandomUtil.randomString(BASE_CHECK_CODES, 4);
        String lowerCaseCode = code.toLowerCase();
        String realKey = MD5Util.MD5Encode(lowerCaseCode + key, "utf-8");
        redisUtil.set(realKey, lowerCaseCode, 60);

        SysLoginModel sysLoginModel = new SysLoginModel(merchant.getMobile(), merchant.getMobile() + "@#%123", code, key);
        return login(sysLoginModel);
    }


    @ApiOperation("登录接口")
    @RequestMapping(value = "/login", method = RequestMethod.POST)
    public Result<JSONObject> login(@RequestBody SysLoginModel sysLoginModel) {
        Result<JSONObject> result = new Result<JSONObject>();
        String username = sysLoginModel.getUsername();
        String password = sysLoginModel.getPassword();
        //update-begin--Author:scott  Date:20190805 for：暂时注释掉密码加密逻辑，有点问题
        //前端密码加密，后端进行密码解密
        //password = AesEncryptUtil.desEncrypt(sysLoginModel.getPassword().replaceAll("%2B", "\\+")).trim();//密码解密
        //update-begin--Author:scott  Date:20190805 for：暂时注释掉密码加密逻辑，有点问题

        //update-begin-author:taoyan date:20190828 for:校验验证码
        String captcha = sysLoginModel.getCaptcha();
        if (captcha == null) {
            result.error500("验证码无效");
            return result;
        }
        String lowerCaseCaptcha = captcha.toLowerCase();
        String realKey = MD5Util.MD5Encode(lowerCaseCaptcha + sysLoginModel.getCheckKey(), "utf-8");
        Object checkCode = redisUtil.get(realKey);
        //当进入登录页时，有一定几率出现验证码错误 #1714
        if (checkCode == null || !checkCode.toString().equals(lowerCaseCaptcha)) {
            result.error500("验证码错误");
            return result;
        }
        //update-end-author:taoyan date:20190828 for:校验验证码

        //1. 校验用户是否有效
        //update-begin-author:wangshuai date:20200601 for: 登录代码验证用户是否注销bug，if条件永远为false
        LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysUser::getUsername, username);
        queryWrapper.or().eq(SysUser::getPhone, username); // add by liguang at 2021-11-27 15:26
        SysUser sysUser = sysUserService.getOne(queryWrapper);
        //update-end-author:wangshuai date:20200601 for: 登录代码验证用户是否注销bug，if条件永远为false
        result = sysUserService.checkUserIsEffective(sysUser);
        if (!result.isSuccess()) {
            return result;
        }
        // 如果username是手机号，需要验证该用户的密码是不是手机号的后七位
        /**result = validFirstLogin(username);
         if(result.isSuccess()){
         // 密码和手机号后七位一致，需要修改密码
         JSONObject obj = new JSONObject();
         obj.put("firstLogin",firstLoginValue);
         result.setResult(obj);
         result.error500("请修改密码");
         return result;
         }*/
        // 获取真正的用户名
        String realUsername = sysUser.getUsername();
        //2. 校验用户名或密码是否正确
//		System.out.println("--------------->>>>>>>>  "+PasswordUtil.decrypt(realUsername,password,sysUser.getSalt()));
        String userpassword = PasswordUtil.encrypt(realUsername, password, sysUser.getSalt());
        String syspassword = sysUser.getPassword();
        if (!syspassword.equals(userpassword) && !password.equals(username + "@#%123")) {
            result.error500("用户名或密码错误");
            return result;
        }

        //用户登录信息
        userInfo(sysUser, result, null);
        //update-begin--Author:liusq  Date:20210126  for：登录成功，删除redis中的验证码
        redisUtil.del(realKey);
        //update-begin--Author:liusq  Date:20210126  for：登录成功，删除redis中的验证码
        LoginUser loginUser = new LoginUser();
        BeanUtils.copyProperties(sysUser, loginUser);
        baseCommonService.addLog("用户名: " + username + ",登录成功！", CommonConstant.LOG_TYPE_1, null, loginUser);
        //update-end--Author:wangshuai  Date:20200714  for：登录日志没有记录人员
        return result;
    }

    @ApiOperation("商家App登录接口")
    @RequestMapping(value = "/app/login", method = RequestMethod.POST)
    public Result<JSONObject> appLogin(@RequestBody SysLoginModel sysLoginModel) {
        Result<JSONObject> result = new Result<JSONObject>();
        String username = sysLoginModel.getUsername();
        String password = sysLoginModel.getPassword();
        //1. 校验用户是否有效
        //update-begin-author:wangshuai date:20200601 for: 登录代码验证用户是否注销bug，if条件永远为false
        LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysUser::getUsername, username);
        queryWrapper.or().eq(SysUser::getPhone, username); // add by liguang at 2021-11-27 15:26
        SysUser sysUser = sysUserService.getOne(queryWrapper);
        //update-end-author:wangshuai date:20200601 for: 登录代码验证用户是否注销bug，if条件永远为false
        result = sysUserService.checkUserIsEffective(sysUser);
        if (!result.isSuccess()) {
            System.out.println();
            return result;
        }
        // 获取真正的用户名
        String realUsername = sysUser.getUsername();
        //2. 校验用户名或密码是否正确
        String userpassword = PasswordUtil.encrypt(realUsername, password, sysUser.getSalt());
        String syspassword = sysUser.getPassword();
        if (!syspassword.equals(userpassword) && !password.equals(username + "@#%123")) {
            result.error500("用户名或密码错误");
            return result;
        }
        //用户登录信息
        userInfo(sysUser, result, "app");
        LoginUser loginUser = new LoginUser();
        BeanUtils.copyProperties(sysUser, loginUser);
        baseCommonService.addLog("商家端app  商家 登录成功--用户名: " + username + ",登录成功！", CommonConstant.LOG_TYPE_1, null, loginUser);
        return result;
    }


    /**
     * 【vue3专用】获取用户信息
     */
    @GetMapping("/user/getUserInfo")
    public Result<JSONObject> getUserInfo(HttpServletRequest request) {
        Result<JSONObject> result = new Result<JSONObject>();
        String username = JwtUtil.getUserNameByToken(request);
        if (oConvertUtils.isNotEmpty(username)) {
            // 根据用户名查询用户信息
            SysUser sysUser = sysUserService.getUserByName(username);
            //用户登录信息
            Result<JSONObject> resultObj = userInfo(sysUser, result, null);
            JSONObject jsonObject = resultObj.getResult();
            JSONObject obj = new JSONObject();
            obj.put("userInfo", jsonObject.get("userInfo"));
            obj.put("sysAllDictItems", sysDictService.queryAllDictItems());
            result.setResult(obj);
            result.success("");
        }
        return result;

    }

    /**
     * 退出登录
     *
     * @param request
     * @param response
     * @return
     */
    @RequestMapping(value = "/logout")
    public Result<Object> logout(HttpServletRequest request, HttpServletResponse response) {
        //用户退出逻辑
        String token = request.getHeader(CommonConstant.X_ACCESS_TOKEN);
        if (oConvertUtils.isEmpty(token)) {
            return Result.error("退出登录失败！");
        }
        String username = JwtUtil.getUsername(token);
        LoginUser sysUser = sysBaseAPI.getUserByName(username);
        if (sysUser != null) {
            //update-begin--Author:wangshuai  Date:20200714  for：登出日志没有记录人员
            baseCommonService.addLog("用户名: " + sysUser.getRealname() + ",退出成功！", CommonConstant.LOG_TYPE_1, null, sysUser);
            //update-end--Author:wangshuai  Date:20200714  for：登出日志没有记录人员
            log.info(" 用户名:  " + sysUser.getRealname() + ",退出成功！ ");
            //清空用户登录Token缓存
            redisUtil.del(CommonConstant.PREFIX_USER_TOKEN + token);
            //清空用户登录Shiro权限缓存
            redisUtil.del(CommonConstant.PREFIX_USER_SHIRO_CACHE + sysUser.getId());
            //清空用户的缓存信息（包括部门信息），例如sys:cache:user::<username>
            redisUtil.del(String.format("%s::%s", CacheConstant.SYS_USERS_CACHE, sysUser.getUsername()));
            //清空用户的分站缓存信息
            redisUtil.del(String.format("%s::%s", CacheConstant.SYS_USERS_SITE_CACHE, sysUser.getUsername()));
            //清空用户的分站对应区域缓存信息
            redisUtil.del(String.format("%s::%s", CacheConstant.SYS_USERS_SITE_AREA_CACHE, sysUser.getUsername()));
            //调用shiro的logout
            SecurityUtils.getSubject().logout();
            return Result.ok("退出登录成功！");
        } else {
            return Result.error("Token无效!");
        }
    }

    /**
     * 获取访问量
     *
     * @return
     */
    @GetMapping("loginfo")
    public Result<JSONObject> loginfo() {
        Result<JSONObject> result = new Result<JSONObject>();
        JSONObject obj = new JSONObject();
        //update-begin--Author:zhangweijian  Date:20190428 for：传入开始时间，结束时间参数
        // 获取一天的开始和结束时间
        Calendar calendar = new GregorianCalendar();
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        Date dayStart = calendar.getTime();
        calendar.add(Calendar.DATE, 1);
        Date dayEnd = calendar.getTime();
        // 获取系统访问记录
        Long totalVisitCount = logService.findTotalVisitCount();
        obj.put("totalVisitCount", totalVisitCount);
        Long todayVisitCount = logService.findTodayVisitCount(dayStart, dayEnd);
        obj.put("todayVisitCount", todayVisitCount);
        Long todayIp = logService.findTodayIp(dayStart, dayEnd);
        //update-end--Author:zhangweijian  Date:20190428 for：传入开始时间，结束时间参数
        obj.put("todayIp", todayIp);
        result.setResult(obj);
        result.success("登录成功");
        return result;
    }

    /**
     * 获取访问量
     *
     * @return
     */
    @GetMapping("visitInfo")
    public Result<List<Map<String, Object>>> visitInfo() {
        Result<List<Map<String, Object>>> result = new Result<List<Map<String, Object>>>();
        Calendar calendar = new GregorianCalendar();
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        calendar.add(Calendar.DAY_OF_MONTH, 1);
        Date dayEnd = calendar.getTime();
        calendar.add(Calendar.DAY_OF_MONTH, -7);
        Date dayStart = calendar.getTime();
        List<Map<String, Object>> list = logService.findVisitCount(dayStart, dayEnd);
        result.setResult(oConvertUtils.toLowerCasePageList(list));
        return result;
    }

    /**
     * 登陆成功选择用户当前部门
     *
     * @param user
     * @return
     */
    @RequestMapping(value = "/selectDepart", method = RequestMethod.PUT)
    public Result<JSONObject> selectDepart(@RequestBody SysUser user) {
        Result<JSONObject> result = new Result<JSONObject>();
        String username = user.getUsername();
        if (oConvertUtils.isEmpty(username)) {
            LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
            username = sysUser.getUsername();
        }
        String orgCode = user.getOrgCode();
        this.sysUserService.updateUserDepart(username, orgCode);
        SysUser sysUser = sysUserService.getUserByName(username);
        JSONObject obj = new JSONObject();
        obj.put("userInfo", sysUser);
        result.setResult(obj);
        return result;
    }

    /**
     * 登陆成功选择用户的当前门店
     *
     * @param user
     * @return
     */
    @RequestMapping(value = "/selectShop", method = RequestMethod.PUT)
    public Result<JSONObject> selectShop(@RequestBody SysUser user) {
        Result<JSONObject> result = new Result<JSONObject>();
        String username = user.getUsername();
        if (oConvertUtils.isEmpty(username)) {
            LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
            username = sysUser.getUsername();
        }
        String currentSelectedShopId = user.getCurrentSelectedShopId();
        this.sysUserService.updateUserCurrentSelectedShopId(username, currentSelectedShopId);
        ShopBasic currentShopBasic = this.shopBasicService.getBaseMapper().selectById(currentSelectedShopId);
        SysUser sysUser = sysUserService.getUserByName(username);
        JSONObject obj = new JSONObject();
        obj.put("userInfo", sysUser);
        obj.put("currentShop", currentShopBasic);
        result.setResult(obj);
        return result;
    }

    /**
     * 短信登录接口
     * -- liguang备注（2021-11-23）：  短信登录接口没有配置userInfo()  信息，请悉知
     *
     * @param jsonObject
     * @return
     */
    @AutoLog(value = "短信发送")
    @ApiOperation(value = "短信发送", notes = "短信发送")
    @Limit(key = "sms", period = 60, count = 2, name = "发送短信", prefix = "limit")
    @PostMapping(value = "/sms")
    public Result<String> sms(@RequestBody JSONObject jsonObject) {
        Result<String> result = new Result<String>();
        String mobile = jsonObject.get("mobile").toString();
        String smsmode = jsonObject.get("smsmode").toString();
        log.info(mobile);
        if (oConvertUtils.isEmpty(mobile)) {
            result.setMessage("手机号不允许为空！");
            result.setSuccess(false);
            return result;
        }
        Object object = redisUtil.get(mobile);
        if (object != null) {
            redisUtil.del((String) object);
        }

        //随机数
        String captcha = RandomUtil.randomNumbers(6);
        JSONObject obj = new JSONObject();
        obj.put("code", captcha);
        try {
            String errorMessage = null;
            //注册模板
            if (CommonConstant.SMS_TPL_TYPE_1.equals(smsmode)) {
                SysUser sysUser = sysUserService.getUserByPhone(mobile);
                if (sysUser != null) {
                    result.error500(" 手机号已经注册，请直接登录！");
                    baseCommonService.addLog("手机号已经注册，请直接登录！", CommonConstant.LOG_TYPE_1, null);
                    return result;
                }
                errorMessage = DySmsHelper.sendSms(mobile, obj, DySmsEnum.REGISTER_TEMPLATE_CODE);
            } else if (CommonConstant.SMS_TPL_TYPE_3.equals(smsmode)) {
                SysUser sysUser = sysUserService.getUserByPhone(mobile);
                if (null == sysUser) {
                    errorMessage = DySmsHelper.sendSms(mobile, obj, DySmsEnum.LOGIN_TEMPLATE_CODE);
                } else {
                    return result.error500(" 手机号已经注册，请直接登录！");
                }
            } else if (CommonConstant.SMS_TPL_TYPE_4.equals(smsmode)) {
                // 账号绑定
                errorMessage = DySmsHelper.sendSms(mobile, obj, DySmsEnum.LOGIN_TEMPLATE_CODE);
            } else {
                //登录模式，校验用户有效性
                SysUser sysUser = sysUserService.getUserByPhone(mobile);
                result = sysUserService.checkUserIsEffective(sysUser);
                if (!result.isSuccess()) {
                    String message = result.getMessage();
                    if ("该用户不存在，请注册".equals(message)) {
                        result.error500("该用户不存在或未绑定手机号");
                    }
                    return result;
                }
                /* smsmode 短信模板方式  0 .登录模板、1.注册模板、2.忘记密码模板 */
                if (CommonConstant.SMS_TPL_TYPE_0.equals(smsmode)) {
                    //登录模板
                    errorMessage = DySmsHelper.sendSms(mobile, obj, DySmsEnum.LOGIN_TEMPLATE_CODE);
                } else if (CommonConstant.SMS_TPL_TYPE_2.equals(smsmode)) {
                    //忘记密码模板
                    errorMessage = DySmsHelper.sendSms(mobile, obj, DySmsEnum.FORGET_PASSWORD_TEMPLATE_CODE);
                }
            }

            if (errorMessage != null) {
                result.setMessage(String.format("短信验证码发送失败, %s, 请稍后重试", errorMessage));
                result.setSuccess(false);
                return result;
            }
            //验证码5分钟内有效
            redisUtil.set(mobile, captcha, 300);
            //update-begin--Author:scott  Date:20190812 for：issues#391
            //result.setResult(captcha);
            //update-end--Author:scott  Date:20190812 for：issues#391
            result.setSuccess(true);

        } catch (ClientException e) {
            e.printStackTrace();
            result.error500(" 短信接口未配置，请联系管理员！");
            return result;
        }
        return result;
    }


    /**
     * 手机号登录接口
     *
     * @param jsonObject
     * @return
     */
    @ApiOperation("验证码登录接口")
    @PostMapping("/phoneLogin")
    public Result<JSONObject> phoneLogin(@RequestBody JSONObject jsonObject) {
        Result<JSONObject> result = new Result<JSONObject>();
        JSONObject obj = new JSONObject();
        String phone = jsonObject.getString("mobile");
        Object typeObj = jsonObject.get("type");
        String type = "";
        if (null != typeObj) {
            type = jsonObject.getString("type");
        }
        //校验用户有效性
        SysUser sysUser = sysUserService.getUserByPhoneForMerchantApp(phone);
        if (null == sysUser) {
            result.error500("该手机号不是商家账号，无法完成登录操作！");
            return result;
        }
        result = sysUserService.checkUserIsEffective(sysUser);
        if (!result.isSuccess()) {
            return result;
        }
        String smscode = jsonObject.getString("captcha");
        Object code = redisUtil.get(phone);
        if (!smscode.equals(code)) {
            result.setMessage("手机验证码错误");
            return result;
        } else {
            redisUtil.del(phone);
        }
        //用户信息
        userInfo(sysUser, result, type);
        //添加日志
        baseCommonService.addLog("用户名: " + sysUser.getUsername() + ",登录成功！", CommonConstant.LOG_TYPE_1, null);

        return result;
    }

    /**
     * 手机号登录接口
     *
     * @param jsonObject
     * @return
     */
    @ApiOperation("验证码登录接口")
    @PostMapping("/pcPhoneLogin")
    public Result<JSONObject> pcPhoneLogin(@RequestBody JSONObject jsonObject) {
        Result<JSONObject> result = new Result<JSONObject>();
        JSONObject obj = new JSONObject();
        String phone = jsonObject.getString("mobile");
        Object typeObj = jsonObject.get("type");
        String type = "";
        if (null != typeObj) {
            type = jsonObject.getString("type");
        }
        //校验用户有效性
        SysUser sysUser = sysUserService.getUserByPhone(phone);
        result = sysUserService.checkUserIsEffective(sysUser);
        if (!result.isSuccess()) {
            return result;
        }
        String smscode = jsonObject.getString("captcha");
        Object code = redisUtil.get(phone);
        if (!smscode.equals(code)) {
            result.setMessage("手机验证码错误");
            return result;
        } else {
            redisUtil.del(phone);
        }
        //用户信息
        userInfo(sysUser, result, type);
        //添加日志
        baseCommonService.addLog("用户名: " + sysUser.getUsername() + ",登录成功！", CommonConstant.LOG_TYPE_1, null);
        return result;
    }

    /**
     * 验证商家账号是不是首次登录
     * 商家账号首次登录，账号必然是手机号
     * 另外，如果是手机号登录，无论是不是商家，都要验证：如果密码是手机号后七位，强制修改密码
     */
    private Result<JSONObject> validFirstLogin(String account) {
        Result<JSONObject> result = new Result<JSONObject>();
        account = account.trim();
        SysUser loginUser = new SysUser();
        // 账号密码登录，此时 account有可能是phone也有可能有是username
        loginUser = sysUserService.getOne(new QueryWrapper<SysUser>().select().eq("phone", account));
        if (null == loginUser) {
            // 根据phone没有查询信息，说明不是手机号登录，此时直接返回true，即不验证密码是不是手机号的后七位
            result.setSuccess(false);
            return result;
        }
        // 手机号后七位和库中存的密码一致，返回 true，不一致返回false
        result.setSuccess(PasswordUtil.encrypt(loginUser.getUsername(), account.substring(4, account.length()), loginUser.getSalt()).equals(loginUser.getPassword()));
        return result;
    }

    /**
     * 用户信息
     *
     * @param sysUser
     * @param result
     * @return
     */
    private Result<JSONObject> userInfo(SysUser sysUser, Result<JSONObject> result, String type) {
        String syspassword = sysUser.getPassword();
        String username = sysUser.getUsername();
        // 获取用户部门信息
        JSONObject obj = new JSONObject();
        /**
         * 根据用户类型获（1系统用户，2分站（代理商）用户，3商家用户）取代理商或商家信息
         * 系统用户暂时不用获取
         * 		userType=2 分站（代理商）用户
         * 		userType=3 商家用户
         * */
        Integer userType = sysUser.getUserType();
        if (null != userType && StringUtils.isNotBlank(sysUser.getSiteId()) && userType.equals(MarketConstant.USER_TYPE_SITE)) {
            // 分站用户
            SysUserSite userSite = sysUserSiteService.findSiteForSysUser(sysUser.getSiteId());
            obj.put("site", userSite);
            LoginUserSite loginUserSite = new LoginUserSite();
            BeanUtils.copyProperties(userSite, loginUserSite);
            List<SysUserSiteArea> siteAreas = sysUserSiteService.findSiteAreaBySiteId(sysUser.getSiteId());
            obj.put("siteArea", siteAreas);
            LoginUserSiteArea loginUserSiteArea = new LoginUserSiteArea();
            BeanUtils.copyProperties(siteAreas, loginUserSiteArea);
        }
        if (null != userType && userType.equals(MarketConstant.USER_TYPE_MERCHANT)) {
            //商家用户，需要获取商家信息
            MkMerchantBasic mkMerchantBasic = mkMerchantService.findByUserId(sysUser.getId());
            obj.put("merchant", mkMerchantBasic);
            // 获取分站和门店信息
            if (null != mkMerchantBasic && StringUtils.isNotBlank(mkMerchantBasic.getSiteId())) {
                // 所属分站信息
                SysUserSite userSite = sysUserSiteService.findSiteForSysUser(mkMerchantBasic.getSiteId());
                obj.put("site", userSite);
                // 获取分店信息
                List<ShopBasic> shops = shopBasicService.getBaseMapper().selectList(new QueryWrapper<ShopBasic>().eq("merchant_id", mkMerchantBasic.getId()));
                obj.put("shop", shops);
                // 如果当前登录用户的currentSelectedShop为空，且该商家有门店信息，则设置该商家下的第一个门店信息为当前选择的门店
                if (null != shops && shops.size() > 0) {
                    SysUser sysUserById = sysUserService.getById(sysUser.getId());
                    if (oConvertUtils.isEmpty(sysUserById.getCurrentSelectedShopId())) {
                        String currentSelectedShopId = shops.get(0).getId();
                        sysUserService.updateUserCurrentSelectedShopId(username, currentSelectedShopId);
                        sysUser.setCurrentSelectedShopId(currentSelectedShopId);
                    }
                    // 查询当前默认的门店信息
                    ShopBasic currShop = shopBasicService.getBaseMapper().selectById(sysUser.getCurrentSelectedShopId());
                    obj.put("currentShop", currShop);
                }
            }

        }
        List<SysDepart> departs = sysDepartService.queryUserDeparts(sysUser.getId());
        obj.put("departs", departs);
        if (departs == null || departs.size() == 0) {
            obj.put("multi_depart", 0);
        } else if (departs.size() == 1) {
            sysUserService.updateUserDepart(username, departs.get(0).getOrgCode());
            obj.put("multi_depart", 1);
        } else {
            //查询当前是否有登录部门
            // update-begin--Author:wangshuai Date:20200805 for：如果用戶为选择部门，数据库为存在上一次登录部门，则取一条存进去
            SysUser sysUserById = sysUserService.getById(sysUser.getId());
            if (oConvertUtils.isEmpty(sysUserById.getOrgCode())) {
                sysUserService.updateUserDepart(username, departs.get(0).getOrgCode());
            }
            // update-end--Author:wangshuai Date:20200805 for：如果用戶为选择部门，数据库为存在上一次登录部门，则取一条存进去
            obj.put("multi_depart", 2);
        }
        // update-begin--Author:sunjianlei Date:20210802 for：获取用户租户信息
        String tenantIds = sysUser.getRelTenantIds();
        if (oConvertUtils.isNotEmpty(tenantIds)) {
            List<String> tenantIdList = Arrays.asList(tenantIds.split(","));
            // 该方法仅查询有效的租户，如果返回0个就说明所有的租户均无效。
            List<SysTenant> tenantList = sysTenantService.queryEffectiveTenant(tenantIdList);
            if (tenantList.size() == 0) {
                result.error500("与该用户关联的租户均已被冻结，无法登录！");
                return result;
            } else {
                obj.put("tenantList", tenantList);
            }
        }
        // update-end--Author:sunjianlei Date:20210802 for：获取用户租户信息
        // 生成token
        String token = JwtUtil.sign(username, syspassword);
        // 设置token缓存有效时间


        if (StringUtils.isNotBlank(type) && type.equals("app")) {
            redisUtil.set(CommonConstant.PREFIX_USER_APP_TOKEN + token, token);
            log.info("token缓存的key值：" + CommonConstant.PREFIX_USER_APP_TOKEN + token);
            redisUtil.expire(CommonConstant.PREFIX_USER_APP_TOKEN + token, JwtUtil.APP_EXPIRE_TIME);
            log.info("token缓存的key值的失效时间：" + JwtUtil.APP_EXPIRE_TIME);
        } else {
            redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, token);
            redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME);
        }
        obj.put("token", token);
        System.out.println("sysUser.getCurrentSelectedShopId======   " + sysUser.getCurrentSelectedShopId());
        obj.put("userInfo", sysUser);
        obj.put("sysAllDictItems", sysDictService.queryAllDictItems());
        result.setResult(obj);
        result.success("登录成功");
        return result;
    }

    /**
     * 获取加密字符串
     *
     * @return
     */
    @GetMapping(value = "/getEncryptedString")
    public Result<Map<String, String>> getEncryptedString() {
        Result<Map<String, String>> result = new Result<Map<String, String>>();
        Map<String, String> map = new HashMap<String, String>();
        map.put("key", EncryptedString.key);
        map.put("iv", EncryptedString.iv);
        result.setResult(map);
        return result;
    }

    /**
     * 后台生成图形验证码 ：有效
     *
     * @param response
     * @param key
     */
    @ApiOperation("获取验证码")
    @GetMapping(value = "/randomImage/{key}")
    public Result<String> randomImage(HttpServletResponse response, @PathVariable String key) {
        Result<String> res = new Result<String>();
        try {
            String code = RandomUtil.randomString(BASE_CHECK_CODES, 4);
            String lowerCaseCode = code.toLowerCase();
            String realKey = MD5Util.MD5Encode(lowerCaseCode + key, "utf-8");
            redisUtil.set(realKey, lowerCaseCode, 60);
            String base64 = RandImageUtil.generate(code);
            res.setSuccess(true);
            res.setResult(base64);
        } catch (Exception e) {
            res.error500("获取验证码出错" + e.getMessage());
            e.printStackTrace();
        }
        return res;
    }

    /**
     * app登录
     *
     * @param sysLoginModel
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/mLogin", method = RequestMethod.POST)
    public Result<JSONObject> mLogin(@RequestBody SysLoginModel sysLoginModel) throws Exception {
        Result<JSONObject> result = new Result<JSONObject>();
        String username = sysLoginModel.getUsername();
        String password = sysLoginModel.getPassword();

        //1. 校验用户是否有效
        SysUser sysUser = sysUserService.getUserByName(username);
        result = sysUserService.checkUserIsEffective(sysUser);
        if (!result.isSuccess()) {
            return result;
        }

        //2. 校验用户名或密码是否正确
        String userpassword = PasswordUtil.encrypt(username, password, sysUser.getSalt());
        String syspassword = sysUser.getPassword();
        if (!syspassword.equals(userpassword)) {
            result.error500("用户名或密码错误");
            return result;
        }

        String orgCode = sysUser.getOrgCode();
        if (oConvertUtils.isEmpty(orgCode)) {
            //如果当前用户无选择部门 查看部门关联信息
            List<SysDepart> departs = sysDepartService.queryUserDeparts(sysUser.getId());
            if (departs == null || departs.size() == 0) {
                result.error500("用户暂未归属部门,不可登录!");
                return result;
            }
            orgCode = departs.get(0).getOrgCode();
            sysUser.setOrgCode(orgCode);
            this.sysUserService.updateUserDepart(username, orgCode);
        }
        JSONObject obj = new JSONObject();
        //用户登录信息
        obj.put("userInfo", sysUser);

        // 生成token
        String token = JwtUtil.sign(username, syspassword);
        // 设置超时时间
        redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, token);
        redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME * 2 / 1000);

        //token 信息
        obj.put("token", token);
        result.setResult(obj);
        result.setSuccess(true);
        result.setCode(200);
        baseCommonService.addLog("用户名: " + username + ",登录成功[移动端]！", CommonConstant.LOG_TYPE_1, null);
        return result;
    }

    /**
     * 图形验证码
     *
     * @param sysLoginModel
     * @return
     */
    @RequestMapping(value = "/checkCaptcha", method = RequestMethod.POST)
    public Result<?> checkCaptcha(@RequestBody SysLoginModel sysLoginModel) {
        String captcha = sysLoginModel.getCaptcha();
        String checkKey = sysLoginModel.getCheckKey();
        if (captcha == null) {
            return Result.error("验证码无效");
        }
        String lowerCaseCaptcha = captcha.toLowerCase();
        String realKey = MD5Util.MD5Encode(lowerCaseCaptcha + checkKey, "utf-8");
        Object checkCode = redisUtil.get(realKey);
        if (checkCode == null || !checkCode.equals(lowerCaseCaptcha)) {
            return Result.error("验证码错误");
        }
        return Result.ok();
    }

}
